#include <iostream>
using namespace std;

class B1
{
public:
  B1() { cout << "B1::B1" << endl; }
  ~ B1() { cout << "B1::~B1" << endl; }
};

class D11: public B1
{
public:
  D11() { cout << "D11::D11" << endl; }
  ~ D11() { cout << "D11::~D11" << endl; }
};

class D12: public D11
{
public:
  D12() 
  { 
    cout << "D12::D12" << endl; 
    data = new int[100]; 
  }
  ~ D12() 
  { 
    cout << "D12::~D12" << endl; 
    delete [] data; 
  }
private:
  int * data;
};

class B2
{
public:
  B2() { cout << "B2::B2" << endl; }
  virtual ~ B2() { cout << "B2::~B2" << endl; }
};

class D21: public B2
{
public:
  D21() 
  { 
    cout << "D21::D21" << endl; 
    data = new int[100]; 
  }
  ~ D21() 
  { 
    cout << "D21::~D21" << endl;  
    delete [] data; 
  }
  int * data;
};

class D22: public D21
{
public:
  D22() { cout << "D22::D22" << endl; }
  ~ D22() { cout << "D22::~D22" << endl; }
};

int main(int argc, char * argv[])
{
  cout << "B1 * b1 = new D12;" << endl;
  B1 * b1 = new D12;  // all three constructors are called

  cout << endl << "B2 * b2 = new D22;" << endl;
  B2 * b2 = new D22;  // all three constructors are called

  cout << endl << "delete b1;" << endl;
  delete b1;  // only one destructor is called

  cout << endl << "delete b2;" << endl;
  delete b2;  // all three destructors are called
  return 0;
}

/*
  output

B1 * b1 = new D12;
B1::B1
D11::D11
D12::D12

B2 * b2 = new D22;
B2::B2
D21::D21
D22::D22

delete b1;
B1::~B1

delete b2;
D22::~D22
D21::~D21
B2::~B2
*/

/*

Why should destructors be virtual but constructors do not have to be virtual?

The answer is that constructors are always virtual. This is enforced by compilers.

When an object of a derived class is created,
1. The constructor of the base class is *always* called first.
2. The constructor of the derived class is then called.
There is no exception.

When an object of a derived class is destroyed,
1. The destructor of the derived class *should* be called first.
2. The destructor of the base class is then called.

Notice that the reverse orders.

 Problems arise if the destructor of a base class is not
 virtual and the destructor of a derived class allocates memory.

 Consider the attached example, when creating both objects
 b1 and b2, B1::B1 and B2::B2 are called first.

 Since B1::~B1 is not virtual, only the destructor of the
 based class, i.e. B1::~B1, is called.  This is the situation
 for b1, even though b1 is actually an object of D12.

 D12::D12 allocates memory and D12::~D12 releases memory.
 Although D12 is correctly written, this program leaks memory.
 The leak occurs because B1's destructor is not virtual.

 You should always make destructors virtual.

 Obviously, the discussion here applies to C++ only since
 Java has no destructors.
 *
 */
